#! /usr/bin/env python
# -*- coding: utf-8 -*-

""" 
Classes Prototype for 
pySkySim: a Sky Simulator for MIRI instrument simulators.


Lingo:
    
Source: an astronomical object, with an spatial and spectral distribution
of light.

:History:

21 02 2015: Created

@author: Ruyman Azzollini

"""
from __future__ import absolute_import, unicode_literals, division, print_function

from pdb import set_trace as stop

import numpy as np
#from astropy import coordinates


from pySkySim import sed


# List all classes and global functions here.

__all__ = ['SkyScene']

class SkyScene(object):
    """ 
    Parent Class for Astronomical Sources.
    """
    
    
    def __init__(self,*args,**kwargs):
        """ """
        
        self.SED = None
        
    def __call__(self,Pos,wavel,time=0.):
        """Retrieves the Scene evaluated at some coordinate and wavelength.
        
        Pos: an astrolib.coords.Position object.
        wavel: wavelength.
        
        """ 
        return 0
        
      
    def __add__(self,other):
        """Allows to add more "sources" to the scene."""
        return CompositeSkyScene(self,other,'add')
    
    def __sub__(self,other):
        """Allows to subtract "sources" to the scene."""
        return CompositeSkyScene(self,other,'subtract')

    def __str__(self):
        """Prints Parameters of Object."""
        verbose = '\n\n'        
        #if self.isophotes is not None: verbose += 'isophotes\n' # self.isophotes.__str__()
        #if self.radial is not None: verbose += 'radial\n' # self.radial.__str__()
        if hasattr(self,'SEDobj'): verbose += self.SED.__str__()
        #if self.isovel is not None: verbose += 'isovel' # self.vel.__str__()
        verbose += '\n\n' 
        return verbose
    
    
    def SED(self,wavel,Pos=None):
        """ """
        if hasattr(self, 'losvd'):
           print('wrap SED to provide a spatially dependent SED, given velo-map')
           print('evaluate wrapped SED')
           return np.zeros_like(wavel)
        else:
           print('evaluate SEDobj at wavelengths')
           return np.zeros_like(wavel)
    
    def get_SED(self,SEDobj):
        """ """
        canget = issubclass(type(SEDobj),sed.Sed)
        
        if not canget:
            print('object cannot acquire SEDobj of type %s' % str(type(SEDobj)))
            raise RuntimeError
        print('WARNING: CRINGING STEP!')
        # an attribute is replaced by an object
        self.SED = SEDobj
        
                
    #def getLOSVD(self,losvd):
    #    """ """
    #    self.losvdobj = losvd
    #    self.losvdpouch = {}
    #    
    #    if hasattr(self,SEDobj):
    #        self.SEDobj.applyLOSVD(self.losvd)
    
    def plot2D(self,window=[],specwin=[]):
        """(contour) Plots self"""
        print('MISSING: plotting of spatial profile: contour plot')
        return None
        
    def plotspec(self,window=[],specwin=[]):
        """Plots (spatially integrated) spectrum"""
        print('MISSING: plotting of spectrum')
        return None
        

class CompositeSkyScene(SkyScene):
    """
    
    Auxiliary class to implement composition of Astronomical Sources.
    
    """
    
    def __init__(self,source1,source2,operation):
        
        self.comp1= source1
        self.comp2 = source2
        self.operation = operation
    
    def __call__(self,Pos,wavel,time):
        
        if self.operation == 'add':
            return self.comp1(Pos,wavel,time) + self.comp2(Pos,wavel,time)
        elif self.operation == 'subtract':
            return self.comp1(Pos,wavel,time) - self.comp2(Pos,wavel,time)
     
    def __str__(self):
        """Prints parameters of Object(s)."""
        verbose = self.comp1.__str__() + '\nAND\n' +self.comp2.__str__() 
        return verbose
    

# A minimal test is run when this file is run as a main program.
if __name__ == '__main__':
    print("Testing the module\n")
    # Basic code/example test
    print("Test finished.")
